package m.html.list;

import m.common.model.DictionaryModel;
import m.common.model.Model;
import m.html.element.*;
import m.html.element.attr.Align;
import m.html.element.other.DisplayItem;
import m.html.element.other.IElement;
import m.html.element.other.Param;
import m.html.util.IVueListColumn;
import m.html.util.VueListUtil;
import m.system.util.GenerateID;
import m.system.util.ObjectUtil;
import m.system.util.StringUtil;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ListColumn implements IVueListColumn {
	private ListColumnType type;
	private String title;
	private String[] groupTitle;
	private String field;
	private String fieldExpression;
	private String countFieldExpression;
	private int width;
	private Align fixed;
	private Boolean sort=false;
	private ListSortOrder sortOrder=ListSortOrder.NONE;
	private ListCount countType=ListCount.NONE;
	private Boolean filter=false;
	private SearchType filterType=SearchType.HIDDEN_EQ;
	private String dateFormat;//yyyy-MM-dd HH:mm:ss:SSS
	private String numberFormat;//#,##0.00
	private Align align;
	private List<DisplayItem> disItems;
	private String dictType;
	private boolean checkboxDict=false;
	private boolean dictTree=false;
	private final List<String> styles;
	private final List<String> classNames;
	private boolean oper=true;//默认功能可用 比如status列
	private String action="";//特殊列使用 status列为action  image列为查看图片field
	private Integer lineClamp=null;
	private ListEvent linkEvent;//link列使用
	private Boolean copy=false;

	public ListColumn(String title,String field) {
		this(ListColumnType.NORMAL,title, field,100);
	}
	public ListColumn(String title,String field,int width) {
		this(ListColumnType.NORMAL,title,field,width);
	}
	public ListColumn(ListColumnType type,String title,String field) {
		this(type,title,field,100);
	}
	public ListColumn(ListColumnType type,String title,String field,int width) {
		if(StringUtil.isSpace(field)) field="tmp_"+GenerateID.tempKey();
		if(type==ListColumnType.STATUS) this.addParamField(field.replaceAll("status", "oid"));
		this.addParamField(field);
		this.title=title;
		this.field=field;
		this.type=type;
		this.setWidth(width);
		this.align=Align.LEFT;
		this.elementList= new ArrayList<>();
		this.fixed=Align.NONE;
		this.disItems= new ArrayList<>();
		this.styles= new ArrayList<>();
		this.classNames=new ArrayList<>();
	}
	private final Set<String> paramFields= new HashSet<>();
	private ListColumn addParamField(String field) {
		if(StringUtil.isSpace(field)) return this;
		if(field.indexOf("tmp_")==0) return this;
		this.paramFields.add(field);
		return this;
	}
	/**
	 * 获取参数所需的字段
	 * 
	 */
	public Set<String> getParamFields() {
		Set<String> pf = new HashSet<>(this.paramFields);
		for(IListElement ele : elementList) {
			pf.addAll(ele.getParamFields());
		}
		if(type==ListColumnType.IMAGE) {
			pf.add(this.action);
		}
		if(type==ListColumnType.LINK) {
			if(null!=linkEvent) {
				pf.addAll(linkEvent.getParamFields());
			}
		}
		return pf;
	}
	/**
	 * 子元素列表
	 */
	private final List<IListElement> elementList;
	/**
	 * 添加子元素
	 *  element
	 * 
	 */
	public ListColumn addElement(IListElement element) {
		this.elementList.add(element);
		return this;
	}
	public ListColumn setTitle(String title) {
		this.title = title;
		return this;
	}
	public ListColumn setField(String field) {
		this.addParamField(field);
		this.field = field;
		return this;
	}
	public ListColumn setWidth(int width) {
		this.width=width;
		return this;
	}
	public ListColumn setFixed(Align fixed) {
		this.fixed = fixed;
		return this;
	}
	public ListColumn setType(ListColumnType type) {
		this.type = type;
		return this;
	}
	/**
	 * 设置是否排序
	 *  sort
	 * 
	 */
	public ListColumn setSort(Boolean sort) {
		this.sort = sort;
		return this;
	}
	/**
	 * 设置默认排序 设置后开启排序
	 *  order
	 * 
	 */
	public ListColumn setSort(ListSortOrder order) {
		this.sortOrder=order;
		this.sort = true;
		return this;
	}
	/**
	 * 设置操作功能是否可用
	 *  oper
	 * 
	 */
	public ListColumn setOper(boolean oper) {
		this.oper=oper;
		return this;
	}
	/**
	 * 设置合计类型
	 *  countType
	 * 
	 */
	public ListColumn setCount(ListCount countType) {
		this.countType=countType;
		return this;
	}
	public ListCount getCount() {
		return this.countType;
	}

	public String getDictType() {
		return dictType;
	}

	/**
	 * 字典
	 */
	public ListColumn setDictType(String dictType) {
		this.dictType = dictType;
		if(dictType.indexOf("!")>0) this.checkboxDict=true;
		return this;
	}
	/**
	 * 字典
	 */
	public ListColumn setDictType(String dictType,boolean checkboxDict){
		setDictType(dictType);
		this.checkboxDict=checkboxDict;
		return this;
	}
	/**
	 * 字典
	 */
	public <T extends DictionaryModel> ListColumn setDictType(Class<T> clazz){
		return setDictType(clazz.getName());
	}
	/**
	 * 字典
	 */
	public <T extends DictionaryModel> ListColumn setDictType(Class<T> clazz,String key){
		return setDictType(clazz.getName()+":"+key);
	}
	/**
	 * 字典
	 */
	public <T extends Model> ListColumn setDictOption(Class<T> clazz, String field){
		this.checkboxDict=true;
		return setDictType(clazz.getName()+"!"+field);
	}
	public ListColumn setDictTree(boolean dictTree){
		this.dictTree=dictTree;
		return this;
	}

	public boolean isDictTree() {
		return dictTree;
	}

	/**
	 * 特殊列使用   
	 *  action
	 * 
	 */
	public ListColumn setAction(String action) {
		this.action=action;
		return this;
	}
	public ListColumn setFieldExpression(String fieldExpression) {
		this.fieldExpression=fieldExpression;
		return this;
	}
	public ListColumn setFilter(Boolean filter) {
		this.filter = filter;
		return this;
	}
	public ListColumn setFilter(SearchType type) {
		this.filter=true;
		this.filterType=type;
		return this;
	}
	public ListColumn setDateFormat(String dateFormat) {
		this.dateFormat = dateFormat;
		return this;
	}
	public ListColumn setNumberFormat(String numberFormat) {
		this.numberFormat = numberFormat;
		return this;
	}
	public ListColumn setAlign(Align align) {
		this.align=align;
		return this;
	}
	public ListColumn setLineClamp(Integer lineClamp) {
		this.lineClamp = lineClamp;
		return this;
	}
	/**
	 * 添加显示项
	 *  item
	 * 
	 */
	public ListColumn addDisItem(DisplayItem item) {
		this.disItems.add(item);
		return this;
	}
	/**
	 * 添加显示项 单数为值,双数为名称
	 *  vs
	 * 
	 */
	public ListColumn addDisItem(String... vs) {
		this.disItems.addAll(DisplayItem.to(vs));
		return this;
	}
	/**
	 * 设置显示项  可通过ItemsQuery,DisplayItem类实现
	 *  list
	 * 
	 */
	public ListColumn setDisItems(List<DisplayItem> list) {
		this.disItems=list;
		return this;
	} 
	/**
	 * 单元格样式    {text, record, index} 当前列字段，行记录，行
	 *  test    例如:text=='1'
	 *  style  样式 例如: color:#f00;
	 * 
	 */
	public ListColumn addStyle(String test,String style) {
		if(!style.startsWith("'")) style="'"+style+"'";
		this.styles.add("("+test+"?"+style+":'')");
		return this;
	}
	/**
	 * 单元格class    {text, record, index} 当前列字段，行记录，行
	 *  test    例如:text=='1'
	 *  style  样式 例如: text-red;
	 *
	 */
	public ListColumn addClassName(String test,String className) {
		if(!className.startsWith("'")) className="'"+className+"'";
		this.classNames.add("("+test+"?"+className+":'')");
		return this;
	}
	public ListColumn setLinkEvent(ListEvent linkEvent) {
		this.linkEvent = linkEvent;
		return this;
	}
	public ListColumn setGroupTitle(String... groupTitle) {
		this.groupTitle=groupTitle;
		return this;
	}
	public ListColumn setCopy(boolean copy){
		this.copy=copy;
		return this;
	}
	/**
	 * 设置列的合计方式，例：sum(#{fieldAs})
	 */
	public ListColumn setCountFieldExpression(String countFieldExpression) {
		this.countFieldExpression = countFieldExpression;
		return this;
	}

	public String getCountFieldExpression() {
		return countFieldExpression;
	}
	public String getNumberFormat() {
		return StringUtil.noSpace(this.numberFormat);
	}
	public String getDateFormat() {
		return StringUtil.noSpace(this.dateFormat);
	}
	private void setFalse() {
		if(this.field.indexOf("tmp_")==0) {
			this.filter=false;
			this.sort=false;
		}
	}
	public boolean isFalse() {
		return this.field.indexOf("tmp_")==0;
	}
	public String toJsonString() {
		StringBuilder sb=new StringBuilder();
		sb.append("{")
		.append("\"title\":\"").append(StringUtil.conver2JS(this.title)).append("\",");
		sb.append("\"width\":").append(this.width).append(",")
		.append("\"resizable\":true,");
		if(this.fixed!=Align.NONE) sb.append("\"fixed\":\"").append(this.fixed).append("\",");
		if(this.align!=Align.NONE) sb.append("\"align\":\"").append(this.align).append("\",");
		if(this.sort) sb.append("\"sorter\":\"").append(this.sort).append("\",");
		sb.append("\"key\":\"").append(this.field).append("\",");
		try {
			sb.append("\"dataIndex\":").append(ObjectUtil.toString(this.field.split("\\."))).append(",");
		}catch(Exception ignored) {}
		sb.append("\"slots\": {");
		if(this.filter) {
			sb.append("	\"filterDropdown\":\"").append(this.field.replaceAll("\\.", "_")).append("fd\",")
			.append("	\"filterIcon\":\"filter-icon\",");
		}
		sb.append("		\"customRender\":\"").append(this.field.replaceAll("\\.", "_")).append("\"");
		sb.append("  }")
		.append("}");
		return sb.toString();
	}
	public String toExtendString(String actionName,Integer lineClamp) {
		setFalse();
		StringBuilder sb=new StringBuilder();
		Element temp1=Element.tag("template").A("#"+this.field.replaceAll("\\.", "_"),"{text, record, index}");
		StringBuilder style= new StringBuilder("''");
		for(String st : this.styles) style.append("+").append(st);
		StringBuilder className=new StringBuilder("''");
		for(String cn : this.classNames) className.append("+").append(cn);
		this.lineClamp=null==this.lineClamp?lineClamp:this.lineClamp;
		Element tmp=Element.tag("div").A(":style", style.toString()).A(":class",className.toString())
			.A("class", this.lineClamp>0?"td-wrap":"td-inline").A("style", "-webkit-line-clamp:"+this.lineClamp);
		if(this.elementList.isEmpty()) {
			if(this.type==ListColumnType.INDEX) {//序号列
				tmp.A("style","white-space:nowrap;").E(new Text("{{(page.index-1)*page.num+index+1}}"));
			}else if(this.type==ListColumnType.STATUS&&this.oper) {//状态列
				String an=StringUtil.isSpace(this.action)?actionName:this.action;
				String oid=this.field.replaceAll("status", "oid");
				tmp.E(new ListElement("a-popconfirm").addAttr("placement", "left").addAttr("v-if","text=='0'").addAttr("title","确定要停用吗?").addText("<a-tag color=\"processing\">正常</a-tag>")
					.setEvent(new ListEvent("confirm","action/"+an+"/doDisable").addParam(Param.field("model.oid", oid)).setSuccess(SuccessMethod.REFRESH)));
				tmp.E(new ListElement("a-popconfirm").addAttr("placement", "left").addAttr("v-if","text=='9'").addAttr("title","确定要启用吗?").addText("<a-tag color=\"error\">停用</a-tag>")
					.setEvent(new ListEvent("confirm","action/"+an+"/doRecovery").addParam(Param.field("model.oid", oid)).setSuccess(SuccessMethod.REFRESH)));
			}else if(this.type==ListColumnType.IMAGE) {
				tmp=Element.tag("img").A(":src", "text").A("style","margin:-8px;max-height:50px;")
					.setExtend(" @click=\"viewImgPath(record."+this.action+")\"");
			}else if(this.type==ListColumnType.LINK) {
				Element a=Element.tag("a-typography-link").E(VueListUtil.toText(this.dateFormat,this.numberFormat,this.dictType,this.disItems,false));
				if(null!=linkEvent) a=linkEvent.toEventElement(a,null);
				tmp.E(a);
			}else{//文本数字日期字典类型
				tmp.E(VueListUtil.toText(this.dateFormat,this.numberFormat,this.dictType,this.disItems,this.copy));
			}
		}else {
			tmp.E(this.elementList);
		}
		temp1.E(tmp);
		sb.append(temp1);
		//自定义搜索
		if(this.filter) {
			Element temp2=Element.tag("template").A("#"+this.field.replaceAll("\\.", "_")+"fd","{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }");
			Element qc=Element.tag("div").A("style","padding:12px");
			qc.E(Element.tag("a-divider").A("orientation","left").A("style","width:150px;margin:0 0 10px;font-weight:300;").E(new Text("{{column.title}}") ));
			if(!StringUtil.isSpace(this.dictType)) {
				if(this.dictTree){
					qc.E(
						Element.tag("div").A("style","padding:0 0 10px;display:flex;")
						.E(Element.tag("a-tree-select").A("v-model:value","inputParams[column.key]")
							.A(":tree-data","dictTreeOptions('"+this.dictType+"')").A("multiple").A("placeholder","请选择... 支持多选")
							.A(":filterTreeNode","treeSelectFilter").A("style","width:260px;")//.A(":showArrow","true")
							.A(":getPopupContainer", "selectPopup")
						)
					);
				}else if(checkboxDict) {
					qc.E(
						Element.tag("div").A("style","width:260px;max-height:400px;overflow: auto;")
						.E(
							Element.tag("a-checkbox-group").A("v-model:value","inputParams[column.key]")
							.E(
								Element.tag("div").A("v-for","item in dictOptions('"+this.dictType+"')").A("style","padding:0 5px 10px;min-width:100px;")
								.E(Element.tag("a-checkbox").A(":value","item.value").E("{{item.label.length>14?(item.label.substring(0,14)+'...'):item.label}}"))
							)
						)
					);
				}else{
					qc.E(
						Element.tag("div").A("style","padding:0 0 10px;display:flex;")
						.E(Element.tag("a-select").A("v-model:value","inputParams[column.key]")
							.A(":options","dictOptions('"+this.dictType+"')").A("mode","multiple").A("placeholder","请选择... 支持多选")
							.A(":filter-option","selectFilter").A("style","width:260px;")//.A(":showArrow","true")
							.A(":getPopupContainer", "selectPopup")
						)
					);
				}
			}else if(this.disItems.size()>10) {
				List<IElement> rs= new ArrayList<>();
				for(DisplayItem di : this.disItems) {
					rs.add(
						Element.tag("a-select-option").A("key",di.getValue()).A("value",di.getValue()).E(new Text(di.getTitle()))
					);
				}
				qc.E(
					Element.tag("div").A("style","padding:0 0 10px;display:flex;")
					.E(Element.tag("a-select").A("v-model:value","inputParams[column.key]").A("mode","multiple").A("placeholder","请选择... 支持多选")
						.A(":filter-option","selectFilter").A("style","width:260px;")//.A(":showArrow","true")
						.A(":getPopupContainer", "selectPopup")
						.E(rs))
				);
			}else if(!this.disItems.isEmpty()) {
				List<IElement> rs= new ArrayList<>();
				for(DisplayItem di : this.disItems) {
					rs.add(
						Element.tag("div").A("style","padding:0 5px 10px;min-width:100px;")
						.E(Element.tag("a-checkbox").A("value",di.getValue()).E(new Text(di.getTitle())))
					);
				}
				qc.E(
					Element.tag("div").A("style","width:230px;")
					.E(Element.tag("a-checkbox-group").A("v-model:value","inputParams[column.key]")
						.E(rs))
				);
			}else if(this.filterType==SearchType.NUMBER_RANGE||this.filterType==SearchType.HIDDEN_NUMBER_RANGE){
				qc.E(Element.tag("a-space-compact").A("block").A("style","padding:0 0 10px;")
					.E(new InputNumber("inputParams[column.key+'_down']").setPlaceholder("下限").A("style", "width:130px"))
					.E(Element.tag("a-input").A("placeholder","~").A("disabled").A("class","input-split"))
					.E(new InputNumber("inputParams[column.key+'_up']").setPlaceholder("上限").A("style", "width:130px"))
				);
			}else if(this.filterType==SearchType.DATE_RANGE||this.filterType==SearchType.HIDDEN_DATE_RANGE
					||this.filterType==SearchType.DATETIME_RANGE||this.filterType==SearchType.HIDDEN_DATETIME_RANGE) {
				boolean flag=this.filterType==SearchType.DATETIME_RANGE||this.filterType==SearchType.HIDDEN_DATETIME_RANGE;
				qc.E(Element.tag("a-space-compact").A("block").A("style","padding:0 0 10px;")
					.E(new DatePicker("inputParams[column.key+'_down']",flag).setPlaceholder("下限").A("style", flag?"width:170px":"width:130px"))
					.E(Element.tag("a-input").A("placeholder","~").A("disabled").A("class","input-split"))
					.E(new DatePicker("inputParams[column.key+'_up']",flag).setPlaceholder("上限").A("style", flag?"width:170px":"width:130px"))
				);
			}else if(this.filterType==SearchType.YEAR_RANGE||this.filterType==SearchType.HIDDEN_YEAR_RANGE) {
				qc.E(Element.tag("a-space-compact").A("block").A("style","padding:0 0 10px;")
					.E(new YearPicker("inputParams[column.key+'_down']").setPlaceholder("下限").A("style", "width:130px"))
					.E(Element.tag("a-input").A("placeholder","~").A("disabled").A("class","input-split"))
					.E(new YearPicker("inputParams[column.key+'_up']").setPlaceholder("上限").A("style", "width:130px"))
				);
			}else if(this.filterType==SearchType.STR_MANY_LIKE||this.filterType==SearchType.HIDDEN_MANY_LIKE) {
				qc.E(
					Element.tag("a-textarea").A("ref","searchInput").A(":placeholder","'搜索... 支持+号和空格'")
					.A("v-model:value","inputParams[column.key]").A("style","width: 260px; margin-bottom: 8px; display: block")
					.A("@pressEnter","confirm();filterHandle(selectedKeys, column);")
					.A("auto-size")
				);
			}else{
				qc.E(
					Element.tag("a-input").A("ref","searchInput").A(":placeholder","'搜索...'")
					.A("v-model:value","inputParams[column.key]").A("style","width: 260px; margin-bottom: 8px; display: block")
					.A("@pressEnter","confirm();filterHandle(selectedKeys, column);")
				);
			}
			qc.E(
				Element.tag("a-flex").A("justify","flex-end").A("align","center").A("gap","small").A("style","padding-top:3px;")
				.E(
					Element.tag("a-switch").A("v-model:checked","inputParams[column.key+'_not']").A("checked-children","排除").A("un-checked-children","筛选")
				)
				.E(
					Element.tag("a-button").A("type","primary").A("size","small").A("style","width: 75px;")
					.A("@click","confirm();filterHandle(selectedKeys, column);")
					.E(new Text("<template #icon>"+new Icon("icon-icon-33")+"</template>查询"))
				)
				.E(
					Element.tag("a-button").A("size","small").A("style","width: 75px")
					.A("@click","confirm();resetHandle(column);")
					.E(new Text("重置"))
				)
			);
			temp2.E(qc);
			sb.append(temp2);
			// end 自定义搜索
		}
		return sb.toString();
	}
	public String getField() {
		return field;
	}
	public String getType() {
		return type.toString();
	}
	public String getTitle() {
		return title;
	}
	public Boolean getFilter() {
		return filter;
	}
	public SearchType getFilterType() {
		return filterType;
	}
	public List<DisplayItem> getDisItems(){
		return this.disItems;
	}
	public ListSortOrder getSortOrder() {
		return sortOrder;
	}
	public String getFieldExpression() {
		return fieldExpression;
	}
	public int getWidth() {
		return width;
	}
	public Align getAlign() {
		return align;
	}
	public String[] getGroupTitle() {
		return groupTitle;
	}
	public Align getFixed() {
		return fixed;
	}
	@Override
	public String getFieldAs() {
		return getField();
	}
	
}
